using System;
using System.Collections.Generic;
using System.Linq;
using Apache.Cassandra;


namespace Cassandraemon.Operators
{


	abstract class CassandraOperatorBase<T> : ICassandraOperator<T>
	{
		public CassandraContext Context { get; set; }
		
		public Cassandra.Client Client { get; set; }

		public Func<object, object> PostProcessor { get; set; }

		public CassandraOperatorBase () { }
		
		
		public object Operate()
		{
			object obj = OperateInner();
			
			if(PostProcessor != null) obj = PostProcessor(obj);
			
			return obj;			
		}
		
		protected abstract object OperateInner() ;
		
#if TRACE
        internal protected virtual void GetTraceData(List<object> data)
        {
            var client = this.Client;
            data.Add(client.HostName());		
        }
#endif

		protected CassandraEntity<T> MakeCassandraEntity(List<ColumnOrSuperColumn> columnOrSuperColumnList, byte[] key, ColumnParent columnParent)
		{
			var entity = new CassandraEntity<T>();
					
			entity.Context = this.Context;
			entity.Key = key;
			entity.ColumnFamily = columnParent.Column_family;
			entity.SuperColumn = columnParent.Super_column;
			entity.Column = null;
					
			
			T t = (T)Activator.CreateInstance(typeof(T));
			
			if(t is Column)
			{
				entity.Data = (T)(object)columnOrSuperColumnList.ConvertAll(x => x.Column).FirstOrDefault();
			}
			else if(t is SuperColumn)
			{
				entity.Data = (T)(object)columnOrSuperColumnList.ConvertAll(x => x.Super_column).FirstOrDefault();
			}
			else if(t is CounterColumn)
			{
				entity.Data = (T)(object)columnOrSuperColumnList.ConvertAll(x => x.Counter_column).FirstOrDefault();
			}
			else if(t is CounterSuperColumn)
			{
				entity.Data = (T)(object)columnOrSuperColumnList.ConvertAll(x => x.Counter_super_column).FirstOrDefault();
			}
			else if(t is IEnumerable<Column>)
			{
				entity.Data = (T)(object)columnOrSuperColumnList.ConvertAll(x => x.Column);
			}
			else if(t is IEnumerable<SuperColumn>)
			{
				entity.Data = (T)(object)columnOrSuperColumnList.ConvertAll(x => x.Super_column);
			}
			else if(t is IEnumerable<CounterColumn>)
			{
				entity.Data = (T)(object)columnOrSuperColumnList.ConvertAll(x => x.Counter_column);
			}
			else if(t is IEnumerable<CounterSuperColumn>)
			{
				entity.Data = (T)(object)columnOrSuperColumnList.ConvertAll(x => x.Counter_super_column);
			}
			else
			{
				throw new InvalidOperationException("You can specify Column or SuperColumn or ConterColumn or CounterSuperColumn or List<Column> or List<SuperColumn> or List<CounterColumn> or List<CounterSuperColumn> to CassandraEntity's GenericType."); 
			}
			
			return entity;
		}
		                                                           
	}	
	
}
